package net.csdn.business.framework.audit.config;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.common.constant.AuditConstants;
import net.csdn.business.common.enums.AuditEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author wanghang
 * @date 2022/7/5 18:19
 */
@Slf4j
@Data
@RefreshScope
@Configuration
public class AuditStrategyConfig {

    private final static String TIME_RANGE_PRE = "-";

    /**
     * 详情审核开关
     */
    @Value("${audit.enable:false}")
    private Boolean auditEnable;

    /**
     * 审核策略
     * 1-先发后审
     * 2-先审后发
     * 3-分时段执行（0点-9点）
     */
    @Value("${audit.strategy:3}")
    private Integer strategy;

    /**
     * 时间段内 先审后发，否则先发后审
     */
    @Value("${audit.strategy-time-range:0-9}")
    private String timeRange;

    /**
     * 获取审核策略
     *
     * @return
     */
    public Map<Integer, Boolean> getAuditStrategy() {
        Map<Integer, Boolean> strategyMap;
        if (strategy == AuditEnum.AuditStrategyEnum.SEND_FIRST.getCode()) {
            // 先发后审
            log.info("==== 命中先发后审");
            strategyMap = AuditConstants.SEND_FIRST;
        } else if (strategy == AuditEnum.AuditStrategyEnum.AUDIT_FIRST.getCode()) {
            // 先审后发
            log.info("==== 命中先审后发");
            strategyMap = AuditConstants.AUDIT_FIRST;
        } else {
            // 分时段判断
            String[] timeRangeArr = timeRange.split(TIME_RANGE_PRE, -1);
            int crrHour = LocalDateTime.now().getHour();
            int startHour = Integer.parseInt(timeRangeArr[0]);
            int endHour = Integer.parseInt(timeRangeArr[1]);

            // 不跨天区间中、跨天的两个区间中
            boolean hitAudit = crrHour >= startHour && crrHour < endHour || (endHour < startHour && (crrHour >= startHour || crrHour < endHour));
            if (hitAudit) {
                // 先审后发
                log.info("==== 分段审核，时间段：{} 命中-先审后发", timeRange);
                strategyMap = AuditConstants.AUDIT_FIRST;
            } else {
                // 先发后审
                log.info("==== 分段审核，时间段：{} 命中-先发后审", timeRange);
                strategyMap = AuditConstants.SEND_FIRST;
            }
        }
        return strategyMap;
    }

    /**
     * 获取审核状态下的可见性
     *
     * @param auditStatus
     * @return
     */
    public Boolean resVisible(Integer auditStatus) {
        try {
            return getAuditStrategy().get(auditStatus);
        } catch (Exception e) {
            log.error("==== 获取审核状态下的可见性,发生异常：{}", e.getMessage());
            return AuditConstants.AUDIT_FIRST.get(auditStatus);
        }
    }

    /**
     * 根据策略，返回审核状态
     *
     * @return AuditStatusEnum
     */
    public AuditEnum.AuditStatusEnum getAuditStatusEnum() {
        Map<Integer, Boolean> result = this.getAuditStrategy();
        if (result.get(AuditEnum.AuditStatusEnum.AUDITING.getCode())) {
            return AuditEnum.AuditStatusEnum.INIT;
        } else {
            return AuditEnum.AuditStatusEnum.PASS;
        }
    }

    /**
     * 获取当前策略下，可见的审核状态
     *
     * @return
     */
    public List<Integer> getVisibleStatus() {
        List<Integer> result = new LinkedList<>();
        Map<Integer, Boolean> strategyMap = getAuditStrategy();
        for (Map.Entry<Integer, Boolean> entry : strategyMap.entrySet()) {
            Integer status = entry.getKey();
            if (entry.getValue()) {
                result.add(status);
            }
        }
        return result;
    }


    public List<String> getCurrentVisible() {
        List<String> result = new LinkedList<>();
        Map<Integer, Boolean> strategyMap = getAuditStrategy();
        for (Map.Entry<Integer, Boolean> entry : strategyMap.entrySet()) {
            Integer status = entry.getKey();
            if (entry.getValue()) {
                result.add(status.toString());
            }
        }
        return result;
    }


}